package kr.co.bnsmedia.touchconfig;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class DetectionView extends View {

	private static final int DETECTION_BITMAP_HEIGHT = (255 >> 1);

	private static final int DETECTION_MARGIN = 2;
	private static final int DETECTION_WIDTH = g.DETECTION_IMAGE_SIZE + 2*DETECTION_MARGIN;
	private static final int DETECTION_HEIGHT = DETECTION_BITMAP_HEIGHT + 2*DETECTION_MARGIN;

	private int mThreshold = g.DATA_THRESHOLD_DEF;
	private int mXStart = g.DATA_XSTART_DEF;
	private int mXEnd = g.DATA_XEND_DEF;
	private int mMinWidth = g.DATA_MINWIDTH_DEF;
	private int mAverageLight = g.DATA_AVERAGELIGHT_DEF;

	private int[] mMaxData = new int[g.DETECTION_IMAGE_SIZE];
	private int[] mThdData = new int[g.DETECTION_IMAGE_SIZE];
	private List<PixelData> mTouchData = new ArrayList<PixelData>();

	private Bitmap mBitmap = null;
	private Canvas mCanvas = null;
	private Paint mPaintData = null;
	private Paint mPaintThreshold = null;
	private Paint mPaintLimit = null;
	private Paint mPaintTouch = null;

	public DetectionView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		init();
	}

	public DetectionView(Context context, AttributeSet attrs) {
		super(context, attrs);

		init();
	}

	public DetectionView(Context context) {
		super(context);

		init();
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int width = DETECTION_WIDTH, height = DETECTION_HEIGHT;

		switch (widthMeasureSpec) {
		case MeasureSpec.AT_MOST:
			width = Math.min(MeasureSpec.getSize(widthMeasureSpec), width);
			break;
		case MeasureSpec.EXACTLY:
			width = MeasureSpec.getSize(widthMeasureSpec);
			break;
		}

		switch (heightMeasureSpec) {
		case MeasureSpec.AT_MOST:
			height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
			break;
		case MeasureSpec.EXACTLY:
			height = MeasureSpec.getSize(heightMeasureSpec);
			break;
		}

		setMeasuredDimension(width, height);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		canvas.drawBitmap(mBitmap, 0, 0, null);
	}

	public void setThreshold(int threshold) {
		mThreshold = threshold;
		Arrays.fill(mMaxData, 0);
	}

	public void setXStart(int xStart) {
		mXStart = xStart;
	}

	public void setXEnd(int xEnd) {
		mXEnd = xEnd;
	}

	public void setMinWidth(int minWidth) {
		mMinWidth = minWidth;
	}

	public void setAverageLight(int averageLight) {
		mAverageLight = averageLight;
	}

	public void reset() {
		Arrays.fill(mMaxData, 0);
	}

	public void setData(int aDev, int aDlen, byte[] aData) {
		if (g.DETECTION_IMAGE_SIZE == aDlen) {
			int width = 0, light = 0;
			PixelData pixelData = null;

			mTouchData.clear();
			mCanvas.drawColor(Color.BLUE);
			for (int i=0; i<g.DETECTION_IMAGE_SIZE; i++) {
				int data = (aData[i] & 0xFF);
				if (mMaxData[i] < data) {
					mMaxData[i] = data;
					mThdData[i] = (int)(data * mThreshold / 255);
				}
				light += data;

				int x = DETECTION_MARGIN + i;
				int sY = DETECTION_HEIGHT - DETECTION_MARGIN, eYData, eYThreshold;

				eYData = sY - (data >> 1);
				eYThreshold = sY - (mThdData[i] >> 1);
				if (eYData > eYThreshold) {
					mCanvas.drawLine(x, sY, x, eYThreshold, mPaintThreshold);
					mCanvas.drawLine(x, sY, x, eYData, mPaintData);
				} else if (eYData < eYThreshold) {
					mCanvas.drawLine(x, sY, x, eYData, mPaintData);
					mCanvas.drawLine(x, sY, x, eYThreshold, mPaintThreshold);
				} else /*if (eYData == eYThreshold)*/ {
					//mCanvas.drawLine(x, sY, x, eYData, mPaintData);
					mCanvas.drawLine(x, sY, x, eYThreshold, mPaintThreshold);
				}

				if (mXStart > i) {
					continue;
				} else if (mXEnd < i) {
					if (0 < width)	{
						pixelData.end = i;
						mTouchData.add(pixelData);
						width = 0;
					}
					continue;
				}

				if (mThdData[i] > data) {
					if (0 == width++) {
						pixelData = new PixelData();
						pixelData.start = i;
					}
					continue;
				}

				if (mMinWidth <= width)	{
					pixelData.end = i;
					mTouchData.add(pixelData);
				}
				width = 0;
			}

			light = light / (mXEnd - mXStart + 1);
			if (mAverageLight > light) {
				mTouchData.clear();
			}

			mCanvas.drawLine(mXStart, DETECTION_HEIGHT-DETECTION_MARGIN, mXStart, DETECTION_MARGIN, mPaintLimit);
			mCanvas.drawLine(mXEnd, DETECTION_HEIGHT-DETECTION_MARGIN, mXEnd, DETECTION_MARGIN, mPaintLimit);

			for (int i=0; i<mTouchData.size(); i++) {
				int x = DETECTION_MARGIN + mTouchData.get(i).start;
				mCanvas.drawLine(x, DETECTION_HEIGHT-DETECTION_MARGIN, x, DETECTION_MARGIN, mPaintTouch);
				x = DETECTION_MARGIN + mTouchData.get(i).end;
				mCanvas.drawLine(x, DETECTION_HEIGHT-DETECTION_MARGIN, x, DETECTION_MARGIN, mPaintTouch);
			}

			invalidate();
		}
	}

	private void init() {
		Arrays.fill(mMaxData, 0);

		mBitmap = Bitmap.createBitmap(DETECTION_WIDTH, DETECTION_HEIGHT, Bitmap.Config.ARGB_8888);

		mCanvas = new Canvas(mBitmap);
		mCanvas.drawColor(Color.BLUE);

		mPaintData = new Paint();
		mPaintData.setColor(Color.GRAY);
		mPaintThreshold = new Paint();
		mPaintThreshold.setColor(Color.LTGRAY);
		mPaintLimit = new Paint();
		mPaintLimit.setColor(Color.RED);
		mPaintTouch = new Paint();
		mPaintTouch.setColor(Color.GREEN);
	}

	private class PixelData {
		public int start;
		public int end;

		public PixelData() {
			start = 0;
			end = 0;
		}
	}
}
